/*
 * protect.h
 *
 *  Created on: 2016-10-4
 *      Author: m
 */

#ifndef SRC_KERNEL_PROTECT_H_
#define SRC_KERNEL_PROTECT_H_

#include "type.h"

#define INDEX_DUMMY         (0)
#define INDEX_FLAT_C        (1)
#define INDEX_FLAT_RW       (2)
#define INDEX_VIDEO         (3)
#define INDEX_TSS           (4)
#define INDEX_LDT_FIRST     (5)

#define SELECTOR_FLAT_C     (INDEX_FLAT_C * 8)//0x08
#define SELECTOR_FLAT_RW    (INDEX_FLAT_RW * 8)//0x10
#define SELECTOR_VIDEO      ((INDEX_VIDEO * 8)+3)//0x18+3 RPL=3
#define SELECTOR_TSS        (INDEX_TSS*8)//0x20 TSS. 从外层跳到内存时 SS和ESP的值从里面获得.
#define SELECTOR_LDT_FIRST  (INDEX_LDT_FIRST * 8)//0x28

#define SELECTOR_KERNEL_CS  SELECTOR_FLAT_C
#define SELECTOR_KERNEL_DS  SELECTOR_FLAT_RW

#define SA_TIG      0 //gdt
#define SA_TIL      4 //ldt

typedef struct {
    u16 limit;
    u8* base;
} __attribute__((packed)) GDT_PTR;

//;gdt表项结构
//;   _base[24,31]
//;  |         _attr
//;  |        |               _base[0,23]
//;  |        |              |               _limit[0,15]
//;__|__ _____|_____ ________|________ _____|_____
//;byte7 byte6 byte5 byte4 byte3 byte2 byte1 byte0
//;      ===========
//;          |
//;          |
//;          |
//;          |     _G
//;          |    |    _D/B
//;          |    |   |    _O                   _P
//;          |    |   |   |    _AVL           |    _DPL
//;          |    |   |   |   |               |   |    _S
//;          |    |   |   |   | limit[16,19]  |   |   |   type
//;          |   _|_ _|_ _|_ _|_ ___|___     _|_ _|_ _|_ ___|___
//;          |->  7   6   5   4  3 2 1 0      7  6 5  4  3 2 1 0
typedef struct s_descriptor {       /* 共 8 个字节 */
    u16  limit_low;      /* Limit */
    u16  base_low;       /* Base */
    u8   base_mid;       /* Base */
    u8   attr1;          /* P(1) DPL(2) DT(1) TYPE(4) */
    u8   limit_high_attr2;   /* G(1) D(1) 0(1) AVL(1) LimitHigh(4) */
    u8   base_high;      /* Base */
} __attribute__((packed)) DESCRIPTOR;


//;(gdt)门表项结构
//;      _offset[31:16]
//;     |            _attr
//;     |           |            __selector
//;     |           |           |            _offset[0,15]
//;_____|_____ _____|_____ _____|_____ _____|_____
//;byte7 byte6 byte5 byte4 byte3 byte2 byte1 byte0
//;            ===========
//;                 |        _P
//;                 |       |    _DPL
//;                 |       |   |     _S
//;                 |       |   |    |       _TYPE
//;                 |       |   |    |      |         fixed:0     _ParamCount
//;                 |      _|_ _|_  _|_  ___|___       __|__ ____|____
//;                 `-->    7  6 5   4   3 2 1 0       7 6 5 4 3 2 1 0
/* 门描述符 */
typedef struct {
    u16 offset_low; /* Offset Low */
    u16 selector;   /* Selector */
    u8  dcount;     /* 该字段只在调用门描述符中有效。如果在利用
                   调用门调用子程序时引起特权级的转换和堆栈
                   的改变，需要将外层堆栈中的参数复制到内层
                   堆栈。该双字计数字段就是用于说明这种情况
                   发生时，要复制的双字参数的数量。*/
    u8  attr;       /* P(1) DPL(2) DT(1) TYPE(4) */
    u16 offset_high;    /* Offset High */
} __attribute((packed)) GATE;

typedef struct s_tss {
    u32 backlink;
    u32 esp0;   /* stack pointer to use during interrupt */
    u32 ss0;    /*   "   segment  "  "    "        "     */
    u32 esp1;
    u32 ss1;
    u32 esp2;
    u32 ss2;
    u32 cr3;
    u32 eip;
    u32 flags;
    u32 eax;
    u32 ecx;
    u32 edx;
    u32 ebx;
    u32 esp;
    u32 ebp;
    u32 esi;
    u32 edi;
    u32 es;
    u32 cs;
    u32 ss;
    u32 ds;
    u32 fs;
    u32 gs;
    u32 ldt;
    u16 trap;
    u16 iobase; /* I/O位图基址大于或等于TSS段界限，就表示没有I/O许可位图 */
} TSS;

#define GDT_ITEM_COUNT (128)
#define IDT_ITEM_COUNT (256)

/* 中断向量 */
#define INT_0VECTOR_DIVIDE          (0x0)
#define INT_1VECTOR_DEBUG           (0x1)
#define INT_2VECTOR_NMI             (0x2)
#define INT_3VECTOR_BREAKPOINT      (0x3)
#define INT_4VECTOR_OVERFLOW        (0x4)
#define INT_5VECTOR_BOUNDS          (0x5)
#define INT_6VECTOR_INVAL_OP        (0x6)
#define INT_7VECTOR_COPROC_NOT      (0x7)
#define INT_8VECTOR_DOUBLE_FAULT    (0x8)
#define INT_9VECTOR_COPROC_SEG      (0x9)
#define INT_AVECTOR_INVAL_TSS       (0xA)
#define INT_BVECTOR_SEG_NOT         (0xB)
#define INT_CVECTOR_STACK_FAULT     (0xC)
#define INT_DVECTOR_PROTECTION      (0xD)
#define INT_EVECTOR_PAGE_FAULT      (0xE)
#define INT_10VECTOR_COPROC_ERR     (0x10)
#define INT_INDEX20_IRQ0            (0x20)

#define INT_VECTOR_SYSCALL          (0x90)

/* 描述符类型值说明 */
#define DA_32           0x4000  /* 32 位段                */
#define DA_LIMIT_4K     0x8000  /* 段界限粒度为 4K 字节         */
#define DA_DPL0         0x00    /* DPL = 0              */
#define DA_DPL1         0x20    /* DPL = 1              */
#define DA_DPL2         0x40    /* DPL = 2              */
#define DA_DPL3         0x60    /* DPL = 3              */
/* 存储段描述符类型值说明 */
#define DA_DR           0x90    /* 存在的只读数据段类型值      */
#define DA_DRW          0x92    /* 存在的可读写数据段属性值     */
#define DA_DRWA         0x93    /* 存在的已访问可读写数据段类型值  */
#define DA_C            0x98    /* 存在的只执行代码段属性值     */
#define DA_CR           0x9A    /* 存在的可执行可读代码段属性值       */
#define DA_CCO          0x9C    /* 存在的只执行一致代码段属性值       */
#define DA_CCOR         0x9E    /* 存在的可执行可读一致代码段属性值 */
/* 系统段描述符类型值说明 */
#define DA_LDT          0x82    /* 局部描述符表段类型值           */
#define DA_TaskGate     0x85    /* 任务门类型值               */
#define DA_386TSS       0x89    /* 可用 386 任务状态段类型值      */
#define DA_386CGate     0x8C    /* 386 调用门类型值           */
#define DA_386IGate     0x8E    /* 386 中断门类型值           */
#define DA_386TGate     0x8F    /* 386 陷阱门类型值           */

#define SA_RPL0     0
#define SA_RPL1     1
#define SA_RPL2     2
#define SA_RPL3     3

/* 权限 */
#define PRIVILEGE_KRNL  0
#define PRIVILEGE_TASK  1
#define PRIVILEGE_USER  3
/* RPL */
#define RPL_KRNL    SA_RPL0
#define RPL_TASK    SA_RPL1
#define RPL_USER    SA_RPL3

void init_idt_desc(u8 idx, u8 desc_type, int_handler handler, u8 privilege);
void init_descriptor(DESCRIPTOR *p_desc,void* base,u32 limit,u16 attribute);
void init_prot();

#endif /* SRC_KERNEL_PROTECT_H_ */
